#include "DXSniffer.h"
#include "stdio.h" 

struct DXSniffer::VERTEX
{
	FLOAT x, y, z;      // The untransformed, 3D position for the vertex
	DWORD color;        // The vertex color 
	D3DXVECTOR3 norm;   // the vertex normal
	FLOAT       tu, tv;   // The texture coordinates
	static DWORD const FVF;
};
const DWORD DXSniffer::VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_NORMAL; 

void DXSniffer::DrawPrimitiveUsed(IDirect3DDevice9* p_this_pointer, D3DPRIMITIVETYPE p_enumPrimitiveType, 
								  UINT p_uintStartVertex,UINT p_uintPrimitiveCount){

	if (m_bLogCycle)
	{
		IDirect3DVertexBuffer9 *VB = NULL; // Buffer to hold vertexes

		printf("\n-----------------------       Drawing Primitive       -----------------------");
		printf("\nDrawing primitive from Sniffer. \nParameters: %d, %u, %u.",p_enumPrimitiveType, p_uintStartVertex, p_uintPrimitiveCount);

		//	Getting the VB's first vertex
		UINT stride, offset;
		p_this_pointer->GetStreamSource(0,&VB,&offset,&stride); 
		VERTEX* pVerts; 
		VB->Lock( offset + p_uintStartVertex * stride, stride, (void**)&pVerts, D3DLOCK_NOOVERWRITE ); 
			printf("\nThe first vertex is In: %f %f %f", pVerts->x,pVerts->y,pVerts->z);
		VB->Unlock(); 

		VB->Release();
	}
	p_this_pointer->DrawPrimitive(p_enumPrimitiveType, p_uintStartVertex, p_uintPrimitiveCount);
}


void DXSniffer::DrawSubsetUsed(ID3DXMesh* p_this_pointer, DWORD p_dAttribs){

	if (m_bLogCycle)
	{
		printf("\n-----------------------       Drawing Subset       -----------------------");
		printf("\nDrawing subset from Sniffer. \nParameters: %ld.",p_dAttribs);
		printf("\nNumber of faces: %u\t\tNumber of Vertices: %u.",p_this_pointer->GetNumFaces(),p_this_pointer->GetNumVertices());
		
		//	Get the mesh's first 3 vertices
		LPD3DXMESH mesh;

		IDirect3DDevice9* dev;
		p_this_pointer->GetDevice(&dev);
		VERTEX* pVerts;
		p_this_pointer->CloneMeshFVF(D3DXMESH_SYSTEMMEM,VERTEX::FVF,dev,&mesh); 
		mesh->LockVertexBuffer(0,(VOID **) &pVerts); 
		printf("\ngot vertex in %f %f %f ", pVerts->x, pVerts->y, pVerts->z); 
		pVerts++; 
		printf("\ngot second vertex in %f %f %f ", pVerts->x, pVerts->y, pVerts->z);
		pVerts++; 
		printf("\ngot third vertex in %f %f %f ", pVerts->x, pVerts->y, pVerts->z);
		mesh->UnlockVertexBuffer();
	}
	p_this_pointer->DrawSubset(p_dAttribs);
}


void DXSniffer::PresentUsed (	IDirect3DDevice9* p_this_pointer, CONST RECT* p_pSourceRect,
							 CONST RECT* p_pDestRect, HWND p_hDestWindowOverride, CONST RGNDATA* p_pDirtyRegion){

	//	Finishing logging Cycle
	if (m_bLogCycle)
	{
		printf("\n***********************       Presenting Frame       ***********************");
		if (p_pSourceRect || p_pDestRect || p_hDestWindowOverride || p_pDirtyRegion)
			printf("\nOne or more of present parameters are not NULL.");

		m_bLogCycle = false;
	}

	//	Presenting
	p_this_pointer->Present(p_pSourceRect, p_pDestRect, p_hDestWindowOverride, p_pDirtyRegion);

	if (m_bAlternativeView){
		p_this_pointer->Present(NULL,NULL,m_hAlternativeHWnd,NULL);
	}

	//	Starting Logging cycle
	if (m_bPrintToConsole)		
	{
		m_bPrintToConsole = false;
		m_bLogCycle = true;

		printf ("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
		printf ("\n$$$$                                                        $$$$");
		printf ("\n$$$$                     LOG CYCLE                          $$$$");
		printf ("\n$$$$                                                        $$$$");
		printf ("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
	}
}


void DXSniffer::CreateAlternativeView(){
	if (!m_bAlternativeView){
		m_bAlternativeView = true;

		// Show the window
		ShowWindow( m_hAlternativeHWnd, SW_SHOWDEFAULT );
		UpdateWindow( m_hAlternativeHWnd );
	}
	else{

	}
}

DXSniffer::~DXSniffer(){
	if (m_bAlternativeView)
		UnregisterClass( L"DxSniffer Demo Scene", m_wcAlternativeWC.hInstance );
}

LRESULT WINAPI DXSniffer::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){
	return DefWindowProc( hWnd, msg, wParam, lParam );
}

DXSniffer::DXSniffer(): 
m_bPrintToConsole(false), 
m_bLogCycle(false), 
m_bAlternativeView(false){
	WNDCLASSEX tmp = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
						GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
						L"DxSniffer Alternative View", NULL };

	m_wcAlternativeWC = tmp;

	RegisterClassEx( &m_wcAlternativeWC );

	// Create the application's window
	m_hAlternativeHWnd = CreateWindow( L"DxSniffer Alternative View", L"DxSniffer Alternative View",
		WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
		NULL, NULL, m_wcAlternativeWC.hInstance, NULL );
}

